package com.tnsw.coreutils.queuemanager;

import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import static com.tnsw.coreutils.StaticConfig.DEBUGMODE;

import android.util.Log;

public class QM implements Runnable {
	
	private boolean _isPause = false;
	private boolean isRunning = false;
	private String queueName;
	private int sleepInterval = 10;
	private ConcurrentLinkedQueue<QueueInfo> queue = new ConcurrentLinkedQueue<QueueInfo>();

	private iQM iqm;
		
	public QM(String queueName, int sleepInterval) {
		
		this.sleepInterval = sleepInterval;
		this.queueName = queueName;
		Log.i(queueName, "created");
	}
	
	public void resume() {
		this._isPause = false;
	}
	
	public void pause() {
		this._isPause = true;
	}
	
	public boolean isPause() {
		return(this._isPause);
	}
	
	public void addQMListener(iQM iqm) {
		this.iqm = iqm;
	}

	public void start() {
		this.isRunning = true;
		Thread t = new Thread(this);
		t.start();
		
	}
	
	public void stop() {
		this.isRunning = false;
	}
	
	public void run() {
		boolean hasError = false;
		Exception exp = null;
		Log.d(this.queueName, "run() is started.");
		
		while (this.isRunning == true) {
			try {
				while (this.isRunning == true) {
					if (this._isPause == false) {
						QueueInfo qi = this.queue.poll();
						
						if (qi != null) { // Found object in queue.				
							
							if (this.iqm != null) {
								this.iqm.onNewQueueReceived(this, qi);
							}
												
						}
														
						Thread.currentThread().sleep(this.sleepInterval);						
					}

				}
			} catch (NoSuchElementException e0) {
				//this.queue.clear();
				exp = e0;
				Log.e(this.queueName, "NoSuchElementException: clearQueue", e0);
				
			} catch (Exception e) {
				hasError = true;
				exp = e;
				Log.e(this.queueName, exp.toString(), exp);
			}
							
			Log.d(this.queueName, "restarting thread because of exception");
		}

		Log.d(this.queueName, "Exit from run()");
				
	}
	
	public void addNewQueue(QueueInfo qi)  {
		this.queue.add(qi);
		if (DEBUGMODE) Log.i(this.queueName, "New QueueInfo is added. (id=" + qi.getQueueId() + ")");
	}
	
	public String getQueueName() {
		return(this.queueName);
	}
}
